package com.td.library.media.audio;

import com.td.library.ResourceTable;
import com.td.library.config.Constant;
import com.td.library.media.video.ThreadPoolManager;
import com.td.library.utils.FileUtils;
import com.td.library.utils.LogUtil;
import com.td.library.utils.TextUtils;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.audio.*;
import ohos.media.codec.Codec;
import ohos.media.common.BufferInfo;
import ohos.media.common.Source;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * PlayerSlice
 */
public class AudioAbilitySlice extends AbilitySlice {
    private static final String TAG = AudioAbilitySlice.class.getName();

    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);

    private static final int SAMPLE_RATE = 44100;

    private static final int BUFFER_SIZE = 1024;

    private AudioRenderer audioRenderer;

    private Codec codec;

    private boolean isPlaying;

    private Button playButton;
    private String filePath;
    private String fileName;
    private boolean startPlay;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_audio_abilit_slice);
        initFileInfo(intent);
        initComponents();
        initAudioRenderer();
    }

    private void initComponents() {
        playButton = (Button) findComponentById(ResourceTable.Id_playButton);
        playButton.setClickedListener(component -> play());

        Text titleText = (Text) findComponentById(ResourceTable.Id_title_text);
        titleText.setText(fileName);

        Component downloadAudioButton = findComponentById(ResourceTable.Id_download_button);
        downloadAudioButton.setClickedListener(component -> {
            ThreadPoolManager.getInstance().execute(() -> {
                File audioFile = new File(filePath);
                try (FileInputStream fileInputStream = new FileInputStream(audioFile)) {
                    Date date = new Date(System.currentTimeMillis());
                    String strDateFormat = "yyyy-MM-dd HH:mm:ss";
                    SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
                    boolean success = FileUtils.saveToDownloads(getApplicationContext(), fileInputStream, audioFile.getPath(),
                            sdf.format(date) + "————" + audioFile.getName());
                    getUITaskDispatcher().asyncDispatch(() -> {
                        new ToastDialog(getContext())
                                .setText("音频下载是否成功：" + success)
                                .show();
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        });
    }

    private void initAudioRenderer() {
        AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(SAMPLE_RATE)
                .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK)
                .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)
                .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO)
                .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA)
                .build();
        AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo)
                .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM)
                .bufferSizeInBytes(BUFFER_SIZE)
                .isOffload(false)
                .sessionID(AudioRendererInfo.SESSION_ID_UNSPECIFIED)
                .build();
        audioRenderer = new AudioRenderer(audioRendererInfo, AudioRenderer.PlayMode.MODE_STREAM);
        audioRenderer.setVolume(1.0f);
        audioRenderer.setSpeed(1.0f);
        setPlayCallback(audioStreamInfo);
    }

    private void play() {
        if (isPlaying) {
            audioRenderer.pause();
            isPlaying = false;
            playButton.setText("play");
        } else {
            audioRenderer.start();
            decoderAudio();
            isPlaying = true;
            playButton.setText("暂停");
        }
    }

    private void initFileInfo(Intent intent) {
        filePath = intent.getStringParam(Constant.INTENT_STR_FILE_PATH);
        LogUtil.info(TAG, "filePath " + filePath);
        if (TextUtils.isEmpty(filePath)) {
            LogUtil.error(TAG, "initAVElement filePath isEmpty");
            return;
        }
        fileName = FileUtils.getFileName(filePath);
        if (TextUtils.isEmpty(fileName)) {
            LogUtil.error(TAG, "initAVElement filePath isEmpty");
            return;
        }
    }

    private void setPlayCallback(AudioStreamInfo streamInfo) {
        AudioInterrupt audioInterrupt = new AudioInterrupt();
        AudioManager audioManager = new AudioManager();
        audioInterrupt.setStreamInfo(streamInfo);
        audioInterrupt.setInterruptListener((type, hint) -> {
            if (type == AudioInterrupt.INTERRUPT_TYPE_BEGIN && hint == AudioInterrupt.INTERRUPT_HINT_PAUSE) {
                HiLog.info(LABEL_LOG, "%{public}s", "sound paused");
            } else if (type == AudioInterrupt.INTERRUPT_TYPE_BEGIN && hint == AudioInterrupt.INTERRUPT_HINT_STOP) {
                HiLog.info(LABEL_LOG, "%{public}s", "sound stopped");
            } else if (type == AudioInterrupt.INTERRUPT_TYPE_END && (hint == AudioInterrupt.INTERRUPT_HINT_RESUME)) {
                HiLog.info(LABEL_LOG, "%{public}s", "sound resumed");
            } else {
                HiLog.info(LABEL_LOG, "%{public}s", "unknown state");
            }
        });
        audioManager.activateAudioInterrupt(audioInterrupt);
    }

    private void decoderAudio() {
        if (codec == null) {
            codec = Codec.createDecoder();
        } else {
            codec.stop();
        }

        Source source = new Source(filePath);
        codec.setSource(source, null);

        codec.registerCodecListener(new Codec.ICodecListener() {
            @Override
            public void onReadBuffer(ByteBuffer outputBuffer, BufferInfo bufferInfo, int trackId) {
                HiLog.error(LABEL_LOG, "%{public}s", "onReadBuffer ");
                audioRenderer.write(outputBuffer, bufferInfo.size);
                audioRenderer.flush();
            }

            @Override
            public void onError(int errorCode, int act, int trackId) {
                HiLog.error(LABEL_LOG, "%{public}s", "codec registerCodecListener error");
            }
        });
        codec.start();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (codec != null) {
            codec.stop();
        }
        if (audioRenderer != null) {
            audioRenderer.release();
        }
    }
}
